<?php

namespace StudyBuddy\Modules\Search;

use \StudyBuddy\Interfaces\Indexer;
use \StudyBuddy\Registry;
use StudyBuddy\String;

/**
 * Wrapper class for adding Questions
 * and possible Answers to the search index
 * Currently works with MySQL as Index provider
 *
 * In the Future if we switch to Lucene we will
 * rewrite or extend this class
 * to make use of Lucene instead
 *
 * All objects that use this class will
 * not have to be changed because all signatures will
 * remain the same, regardless of whant Index provider
 * we may have
 *
 */
class IndexerMySQL implements Indexer {

    /**
     * Registry Object
     * @var object of type Registry
     */
    protected $oRegistry;

    public function __construct(\StudyBuddy\Registry $oRegistry) {
        $this->oRegistry = $oRegistry;
    }

    /**
     * Record title, intro, qid, url, date
     * into QUESTIONS_TITLE mysql table
     * the purpose of this is to use
     * full-text index capabilities
     * of MYSQL on the question title,
     * so we can easily find 'similar'
     * questions based on titles and can
     * also use this for site search feature
     * to some extent. Cool
     *
     * @param Question $oQuestion
     */
    public function indexQuestion(\StudyBuddy\Question $oQuestion) {
        if (!extension_loaded('pdo_mysql')) {
            d('pdo_mysql not loaded ');

            return $this;
        }

        $res = false;
        $qid = $oQuestion['_id'];
        $title = $oQuestion['title'];
        $body = $oQuestion['b'];
        $url = $oQuestion['url'];
        $string = new String($oQuestion['intro']);
        $intro = $string->asPlainText()->truncate(150)->valueOf();
        $uid = $oQuestion['i_uid'];
        $username = $oQuestion['username'];
        $ulink = $oQuestion['ulink'];
        $avatar = $oQuestion['avtr'];
        $tags_html = $oQuestion['tags_html'];

        d($qid . ' title: ' . $title . ' url: ' . $url . ' intro: ' . $intro);

        $sql = 'INSERT INTO question_title
		(
		qid, 
		title,
		q_body, 
		url, 
		intro, 
		uid,
		username,
		userlink,
		avtr,
		tags_html)
		VALUES (
		:qid, 
		:qtitle, 
		:qbody,
		:qurl, 
		:qintro, 
		:uid,
		:username,
		:userlink,
		:avatar,
		:tags_html)';


        try {
            $sth = $this->oRegistry->Db->makePrepared($sql);
            $sth->bindParam(':qid', $qid, \PDO::PARAM_INT);
            $sth->bindParam(':qtitle', $title, \PDO::PARAM_STR);
            $sth->bindParam(':qbody', $body, \PDO::PARAM_STR);
            $sth->bindParam(':qurl', $url, \PDO::PARAM_STR);
            $sth->bindParam(':qintro', $intro, \PDO::PARAM_STR);
            $sth->bindParam(':tags_html', $tags_html, \PDO::PARAM_STR);
            $sth->bindParam(':uid', $uid, \PDO::PARAM_INT);
            $sth->bindParam(':username', $username, \PDO::PARAM_STR);
            $sth->bindParam(':userlink', $ulink, \PDO::PARAM_STR);
            $sth->bindParam(':avatar', $avatar, \PDO::PARAM_STR);

            $res = $sth->execute();
        } catch (\Exception $e) {

            $err = ('Exception: ' . get_class($e) . ' Unable to insert into mysql because: ' . $e->getMessage() . ' Err Code: ' . $e->getCode() . ' trace: ' . $e->getTraceAsString());
            d('mysql error: ' . $err);

            if ('42S02' === $e->getCode()) {
                if (true === TitleTagsTable::create($this->oRegistry)) {
                    $this->indexTitle($oQuestion);
                }
            } else {
                throw $e;
            }
        }
        d('res: ' . $res);

        return $this;
    }

    /**
     * Remove record for one Question from the
     * Index
     *
     * @param Question $oQuestion
     * @return object $this
     */
    public function removeQuestion(\StudyBuddy\Question $oQuestion) {
        if (!extension_loaded('pdo_mysql')) {
            d('pdo_mysql not loaded ');

            return $this;
        }

        $qid = $oQuestion->offsetGet('_id');
        $sql = 'DELETE FROM question_title WHERE qid = :qid';
        d('about to remove question with qid: ' . $qid);

        try {
            $sth = $sth = $this->oRegistry->Db->makePrepared($sql);
            $sth->bindParam(':qid', $qid, \PDO::PARAM_INT);
            $res = $sth->execute();
            d('res: ' . $res);
        } catch (\Exception $e) {
            $err = ('Exception: ' . get_class($e) . ' Unable to delete question because: ' . $e->getMessage() . ' Err Code: ' . $e->getCode() . ' trace: ' . $e->getTraceAsString());
            d('mysql error: ' . $err);
        }

        return $this;
    }

    /**
     * When question is edited in any way we will
     * run this method to also update
     * the index.
     *
     * @param Question $oQuestion
     */
    public function updateQuestion(\StudyBuddy\Question $oQuestion) {

        if (!extension_loaded('pdo_mysql')) {
            d('pdo_mysql not loaded ');

            return $this;
        }

        $res = false;
        $qid = $oQuestion->offsetGet('_id');
        $title = $oQuestion->offsetGet('title');
        $url = $oQuestion->offsetGet('url');
        $intro = $oQuestion->offsetGet('intro');
        $username = $oQuestion['username'];
        $ulink = $oQuestion['ulink'];
        $avatar = $oQuestion['avtr'];
        $tags_html = $oQuestion['tags_html'];
        $body = $oQuestion['body'];

        d($qid . ' title: ' . $title . ' url: ' . $url . ' intro: ' . $intro);

        $sql = 'UPDATE question_title
		SET 
		title = :qtitle,
		q_body = :qbody,
		url = :qurl, 
		intro = :qintro, 
		username = :username,
		userlink = :userlink,
		avtr = :avatar,
		tags_html = :tags_html
		WHERE qid = :qid';


        try {
            $sth = $this->oRegistry->Db->makePrepared($sql);
            $sth->bindParam(':qid', $qid, \PDO::PARAM_INT);
            $sth->bindParam(':qtitle', $title, \PDO::PARAM_STR);
            $sth->bindParam(':qbody', $body, \PDO::PARAM_STR);
            $sth->bindParam(':qurl', $url, \PDO::PARAM_STR);
            $sth->bindParam(':qintro', $intro, \PDO::PARAM_STR);
            $sth->bindParam(':tags_html', $tags_html, \PDO::PARAM_STR);
            $sth->bindParam(':username', $username, \PDO::PARAM_STR);
            $sth->bindParam(':userlink', $ulink, \PDO::PARAM_STR);
            $sth->bindParam(':avatar', $avatar, \PDO::PARAM_STR);

            $res = $sth->execute();
        } catch (\Exception $e) {

            $err = ('Exception: ' . get_class($e) . ' Unable to insert into mysql because: ' . $e->getMessage() . ' Err Code: ' . $e->getCode() . ' trace: ' . $e->getTraceAsString());
            d('mysql error: ' . $err);

            if ('42S02' === $e->getCode()) {
                if (true === TitleTagsTable::create($this->oRegistry)) {
                    $this->indexTitle($oQuestion);
                }
            } else {
                throw $e;
            }
        }
        d('res: ' . $res);

        return $this;
    }

    /**
     * Remove record belonging to one user
     *
     * @param int $uid id of user (value of _id from USERS collection)
     * @return object $this
     */
    public function removeByUserId($uid) {
        if (!extension_loaded('pdo_mysql')) {
            d('pdo_mysql not loaded ');

            return $this;
        }

        $uid = (int) $uid;
        $sql = 'DELETE FROM question_title WHERE uid = :uid';
        d('about to remove question with uid: ' . $uid);

        try {
            $sth = $sth = $this->oRegistry->Db->makePrepared($sql);
            $sth->bindParam(':uid', $uid, \PDO::PARAM_INT);
            $res = $sth->execute();
            d('res: ' . $res);
        } catch (\Exception $e) {
            $err = ('Exception: ' . get_class($e) . ' Unable to delete question because: ' . $e->getMessage() . ' Err Code: ' . $e->getCode() . ' trace: ' . $e->getTraceAsString());
            d('mysql error: ' . $err);
        }

        return $this;
    }

}
